/*****************************************************************************
 * Copyright (c) 2010 -, Anders All rights reserved
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  Contact: Anders Uddenberg (anders.uddenberg@gmail.com)
 * 
 *
 ****************************************************************************/
package org.easypr.organizer.client.presenter;


import java.util.ArrayList;

import org.easypr.organizer.client.BackboneServiceAsync;
import org.easypr.organizer.client.event.DisplayInformationEvent;
import org.easypr.organizer.shared.MyContact;
import org.easypr.organizer.shared.MyUser;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

// TODO: Auto-generated Javadoc
/**
 * The Class SearchPresenter.
 */
public class SearchPresenter implements Presenter {

	/**
	 * Define the interface the view needs to implement.
	 * 
	 * @author Anders
	 */
	public interface Display {
		
		/**
		 * Sets the data.
		 *
		 * @param searchString the new data
		 */
		void setData(String searchString);

		/**
		 * As widget.
		 * 
		 * @return the widget
		 */
		Widget asWidget();
		
		/**
		 * Gets the search button.
		 *
		 * @return the search button
		 */
		Button getSearchButton();
		
		/**
		 * Gets the search input.
		 *
		 * @return the search input
		 */
		TextBox getSearchInput();
		
		/**
		 * Gets the dropdown search table.
		 *
		 * @return the dropdown search table
		 */
		FlexTable getDropdownSearchTable();
		
		/**
		 * Gets the dropdown selected.
		 *
		 * @return the dropdown selected
		 */
		int getDropdownSelected();
		
		/**
		 * Sets the dropdown selected.
		 *
		 * @param selected the new dropdown selected
		 */
		void setDropdownSelected(int selected);
		
		/**
		 * Gets the dropdown selected row.
		 *
		 * @return the dropdown selected row
		 */
		int getDropdownSelectedRow();
		
		/**
		 * Sets the dropdown selected row.
		 *
		 * @param currentRow the new dropdown selected row
		 */
		void setDropdownSelectedRow(int currentRow);
		
		/**
		 * Gets the dropdown last direction.
		 *
		 * @return the dropdown last direction
		 */
		int getDropdownLastDirection();
		
		/**
		 * Sets the dropdown last direction.
		 *
		 * @param direction the new dropdown last direction
		 */
		void setDropdownLastDirection(int direction);
		
		/**
		 * Sets the live search data.
		 *
		 * @param contacts the new live search data
		 */
		void setLiveSearchData(ArrayList<MyContact> contacts);
	}

	/** The event bus. */
	private final HandlerManager eventBus;
	
	/** The display. */
	private final Display display;
	
	/** The parts. */
	private String[] parts;
	
	/** The backbone rpc. */
	private BackboneServiceAsync backboneRPC;
	
	/** The user. */
	private MyUser user;
	
	/**
	 * Instantiates a new menu presenter.
	 *
	 * @param backboneRPC the backbone rpc
	 * @param eventBus the event bus
	 * @param view the view
	 * @param user the user
	 * @param parts the parts
	 */
	public SearchPresenter(BackboneServiceAsync backboneRPC, HandlerManager eventBus, Display view, MyUser user, String[] parts) {
		this.backboneRPC = backboneRPC;
		this.eventBus = eventBus;
		this.display = view;
		this.user = user;
		this.parts = parts;
	}
	

	/* (non-Javadoc)
	 * @see org.easypr.organizer.client.presenter.Presenter#go(com.google.gwt.user.client.ui.HasWidgets)
	 */
	@Override
	public void go(HasWidgets container) {
		container.clear();
		container.add(display.asWidget());
		bind();
		updateContent();
	}
	
	/**
	 * Bind.
	 */
	private void bind() {
		
		display.getSearchButton().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String searchString = display.getSearchInput().getText().trim();
				if(searchString.length() > 0) {
					History.newItem("search/"+searchString);
				}
			}
		});
		
		display.getSearchInput().addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {
				int last = display.getDropdownLastDirection();
				if(event.getNativeKeyCode() == KeyCodes.KEY_UP) { 
					display.setDropdownLastDirection(KeyCodes.KEY_UP);
					int rowCount = display.getDropdownSearchTable().getRowCount();
					// Clear the table
					for(int i=0; i<rowCount; i++) {
						display.getDropdownSearchTable().getFlexCellFormatter().removeStyleName(i, 0, "dropdown-search-selected");
					}
					
					// Moving up
					int currentRow = display.getDropdownSelectedRow();
					
					if(last > 0 && currentRow > 0) {
						currentRow--;
					} else {
						currentRow = rowCount-1;
					}
					display.getDropdownSearchTable().getFlexCellFormatter().setStyleName(currentRow, 0, "dropdown-search-selected");
					display.setDropdownSelectedRow(currentRow);
					display.getSearchInput().setCursorPos(display.getSearchInput().getText().length());
					display.setDropdownSelected(Integer.parseInt(display.getDropdownSearchTable().getWidget(currentRow, 0).getElement().getId()));
				
				
				} else if(event.getNativeKeyCode() == KeyCodes.KEY_DOWN) {
				
					
					display.setDropdownLastDirection(KeyCodes.KEY_DOWN);
					int rowCount = display.getDropdownSearchTable().getRowCount();
					// Clear the table
					for(int i=0; i<rowCount; i++) {
						display.getDropdownSearchTable().getFlexCellFormatter().removeStyleName(i, 0, "dropdown-search-selected");
					}
					
					// Moving down
					int currentRow = display.getDropdownSelectedRow();
					
					if(last > 0 && rowCount-1 > currentRow) {
						currentRow++;
					} else {
						currentRow = 0;
					}
					//System.out.println("Current row: " + currentRow + ", id: " + Integer.parseInt(display.getDropdownSearchTable().getWidget(currentRow, 0).getElement().getId()));
					display.getDropdownSearchTable().getFlexCellFormatter().setStyleName(currentRow, 0, "dropdown-search-selected");
					display.setDropdownSelectedRow(currentRow);
					display.setDropdownSelected(Integer.parseInt(display.getDropdownSearchTable().getWidget(currentRow, 0).getElement().getId()));
				} else if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					// Gå till den som är vald, om ingen sök
					if(display.getDropdownSelected() > 0) {
						History.newItem("contact/"+display.getDropdownSelected());
					} else {
						if(display.getSearchInput().getText().trim().length() > 0) {
							History.newItem("search/"+display.getSearchInput().getText().trim());
						}
					}
				} else {
					String searchString = display.getSearchInput().getText().trim();
					if(searchString.length() > 0) {
						doLiveSearch(searchString);
					}
				}
			}
		});
		
		
	}
	
	
	/**
	 * Do live search.
	 *
	 * @param search the search
	 */
	private void doLiveSearch(String search) {
		AsyncCallback<ArrayList<MyContact>> callback = new AsyncCallback<ArrayList<MyContact>>() {
			public void onFailure(Throwable caught) {
				eventBus.fireEvent(new DisplayInformationEvent("Unable to perform the requested search!", DisplayInformationEvent.Severity.FAILURE));
			}

			public void onSuccess(ArrayList<MyContact> contacts) {
				display.setLiveSearchData(contacts);
			}
		};
		
		backboneRPC.liveSearch(search, user, callback);
	}
	
	
	/**
	 * Main function to update the content of the container.
	 */
	public void updateContent() {
		if(parts != null && parts.length > 1) {
			display.setData(parts[1]);
		} else {
			display.setData(null);
		}
	}
}
